importCSS("/page/interface_manager/css/index.css");
import api from "../config/api.js";

export default {
    name: "interface_manager",
    template: `
    <div id="interface_manager" lanmu="interface_manager">
        <mySearch @add="tableOperation.addClick" @search="loadData.loadTable">
            <el-input v-model="search.name" placeholder="请输入接口名称" clearable />
            <el-button type="primary" @click="loadData.loadTableList">刷新表</el-button>
        </mySearch>
        <myTable ref="myTableRef" :showPage="false" @page-change="loadData.loadTable">
            <el-table-column type="index" label="序号" width="80" align="center" />
            <el-table-column prop="name" label="接口名"  width="250" align="left" />
            <el-table-column prop="url" label="接口url"  width="400"  align="left" />
            <el-table-column prop="open" label="开放权限" width="100" align="center">
                <template  #default="scope">
                    <span>{{scope.row.open ? "开放" : "-"}}</span>
                </template>
            </el-table-column>
            <el-table-column prop="isLowCode" label="低代码"  width="100" align="center">
                <template  #default="scope">
                    <span>{{scope.row.isLowCode ? "低代码" : "-"}}</span>
                </template>
            </el-table-column>
            <el-table-column prop="testResult" label="测试结果"  width="100" align="center">
                <template  #default="scope">
                    <span v-if="scope.row.children">-</span>
                    <span v-else-if="scope.row.testResult" style="color: blue;font-weight: bolder">通过</span>
                    <span v-else style="color: red;font-weight: bolder">不通过</span>
                </template>
            </el-table-column>
<!--            <el-table-column prop="autoTest" label="自动测试"  width="100" align="center">-->
<!--                <template  #default="scope">-->
<!--                    <span v-if="scope.row.children||scope.row.isLowCode">-</span>-->
<!--                    <el-switch v-else v-model="scope.row.autoTest" @change="tableOperation.autoTest(scope.row)" />-->
<!--                </template>-->
<!--            </el-table-column>-->
            <el-table-column prop="open" label="开放"  width="100" align="center">
                <template  #default="scope">
                    <span v-if="scope.row.children">-</span>
                    <el-switch v-else v-model="scope.row.open" @change="tableOperation.open(scope.row)" />
                </template>
            </el-table-column>
            <el-table-column prop="authentication" label="鉴权"  width="100" align="center">
                <template  #default="scope">
                    <span v-if="scope.row.children">-</span>
                    <el-switch v-else v-model="scope.row.authentication" @change="tableOperation.authentication(scope.row)" />
                </template>
            </el-table-column>
            <el-table-column label="操作" align="center">
                <template  #default="scope">
                    <template v-if="scope.row.children">
                        <el-button type="primary" size="small" @click="tableOperation.copyDirClick(scope.row)">复制目录</el-button>
                        <el-button type="info" size="small" @click="tableOperation.copyClick(scope.row)">复制</el-button>
                        <el-button type="warning" :disabled="!scope.row.isLowCode" size="small" @click="tableOperation.editClick(scope.row)">编辑</el-button>
                    </template>
                    <template v-else-if="scope.row.isLowCode">
                        <el-button size="small" @click="tableOperation.configClick(scope.row)">一键配置</el-button>
                        <el-button type="info" size="small" @click="tableOperation.copyClick(scope.row)">复制</el-button>
                        <el-button type="success" size="small" @click="tableOperation.ruleClick(scope.row)">规则</el-button>
                        <el-button type="primary" size="small" @click="tableOperation.testClick(scope.row)">测试</el-button>
                        <el-button type="warning" size="small" @click="tableOperation.editClick(scope.row)">编辑</el-button>
                        <confirmButton @ok="tableOperation.del" :row="scope.row">删除</confirmButton>
                    </template>
                    <template v-else>
                    <el-button size="small" @click="tableOperation.configClick(scope.row)">一键配置</el-button>
                        <el-button type="info" size="small" @click="tableOperation.copyClick(scope.row)">复制</el-button>
                        <el-button type="success" size="small" @click="tableOperation.ruleClick(scope.row)">规则</el-button>
                        <el-button type="primary" size="small" @click="tableOperation.testClick(scope.row)">测试</el-button>
                        <el-button type="danger" size="small" @click="tableOperation.paramClick(scope.row)">参数</el-button>
                    </template>
                </template>
            </el-table-column>
        </myTable>
         <el-dialog
            v-model="copyDirVisible"
            title="复制目录所有接口（只复制低代码接口）"
            width="25%"
          >
            <el-form ref="copyDirFormRef" :model="copyDirFormData" :rules="{
                        name: [{required: true, message: '名称为必填', trigger: 'blur'}],
                        url: [{required: true, message: '接口url为必填', trigger: 'blur'}],
                    }" label-width="80px">
                <el-form-item label="接口名称" prop="name">
                    <el-input v-model="copyDirFormData.name" placeholder="请输入接口名称"></el-input>
                </el-form-item>
                <el-form-item label="接口url" prop="url">
                    <el-input v-model="copyDirFormData.url" placeholder="请输入接口url"></el-input>
                </el-form-item>
            </el-form>
            <template #footer>
              <span class="dialog-footer">
                <el-button @click="copyDirVisible = false">取消</el-button>
                <el-button type="primary" @click="tableOperation.copyDir">保存</el-button>
              </span>
            </template>
        </el-dialog>
         <el-dialog
            v-model="configVisible"
            title="一键配置功能"
            width="25%"
          >
            <el-form ref="configFormRef" :model="configFormData" :rules="{
                        type: [{required: true, message: '类型为必填', trigger: 'change'}],
                        table: [{required: true, message: '数据表为必选', trigger: 'change'}],
                    }" label-width="80px">
                <el-form-item label="类型" prop="type">
                    <el-select style="width: 100%" v-model="configFormData.type" placeholder="请选择类型">
                        <el-option label="新增" value="0"></el-option>
                        <el-option label="编辑" value="1"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="数据表" prop="table">
                    <el-select filterable style="width: 100%" v-model="configFormData.table" placeholder="请选择数据表">
                        <el-option v-for="item in tableList" :key="item.tableName" :label="item.tableComment" :value="item.tableName"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="配置项" prop="info">
                    <el-select style="width: 100%" v-model="configFormData.info" multiple placeholder="请选择配置项">
                        <el-option label="入参" value="0"></el-option>
                        <el-option label="校验" value="1"></el-option>
                        <el-option label="规则" value="2"></el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <template #footer>
              <span class="dialog-footer">
                <el-button @click="configVisible = false">取消</el-button>
                <el-button type="primary" @click="tableOperation.config">保存</el-button>
              </span>
            </template>
        </el-dialog>
        <saveForm ref="saveFormRef" :options="tableDataSource" @save="tableOperation.save"></saveForm>
        <testForm ref="testFormRef" @refresh="loadData.loadTable"></testForm>
        <ruleForm ref="ruleFormRef" @save="tableOperation.saveRule"></ruleForm>
        <paramForm ref="paramFormRef"></paramForm>
    </div>`, setup(props, context) {
        const myTableRef = Vue.ref(), saveFormRef = Vue.ref(), testFormRef = Vue.ref(), ruleFormRef = Vue.ref(),
            paramFormRef = Vue.ref(), tableDataSource = Vue.ref([]), copyDirVisible = Vue.ref(false),
            copyDirFormData = Vue.ref({}),
            configVisible = Vue.ref(false), configFormData = Vue.ref({}), tableList = Vue.ref([]),
            copyDirFormRef = Vue.ref(),
            configFormRef = Vue.ref();
        let myTable, saveForm, testForm, ruleForm, paramForm, swaggerDataSource, swaggerData;
        const search = Vue.reactive({name: ""});
        const loadData = {
            loadSwagger: async () => {
                swaggerDataSource = await api.swagger();
            },
            loadTable: async () => {
                myTable.loading = true
                myTable.tableData = await api.queryTable() || []
                tableDataSource.value = myTable.tableData
                myTable.loading = false
                myTable.tableData = filterNode(JSON.parse(JSON.stringify(tableDataSource.value)), search.name)
            },
            loadTableList: async () => {
                tableList.value = await api.queryTableList() || []
            }
        }
        const getSwaggerRef = (paramType, param, topScheme) => {
            for (let paramKey in paramType) {
                param[paramKey] = paramType[paramKey]?.description
                let keys = Object.keys(paramType[paramKey])
                for (const key of keys) {
                    if (key === '$ref') {
                        let schema = paramType[paramKey][key].replace('#/components/schemas/', '')
                        if (topScheme === schema) {
                            paramType[paramKey] = ['与父级相同']
                            break;
                        }
                        let properties = swaggerData.components.schemas[schema]?.properties || {}
                        let requireds = swaggerData.components.schemas[schema]?.required || []
                        requireds.forEach(key => properties[key].required = true)
                        paramType[paramKey] = properties
                        param[paramKey] = {}
                        getSwaggerRef(paramType[paramKey], param[paramKey], schema)
                        break;
                    }
                    if (key === 'type' && paramType[paramKey][key] === 'array') {
                        if (paramType[paramKey].items['$ref']) {
                            let schema = paramType[paramKey].items['$ref'].replace('#/components/schemas/', '')
                            if (topScheme === schema) {
                                paramType[paramKey] = ['与父级相同']
                                break;
                            }
                            let properties = swaggerData.components.schemas[schema]?.properties || {}
                            let requireds = swaggerData.components.schemas[schema]?.required || []
                            requireds.forEach(key => properties[key].required = true)
                            paramType[paramKey] = [properties]
                            param[paramKey] = [{}]
                            getSwaggerRef(paramType[paramKey][0], param[paramKey][0], schema)
                        }
                        break;
                    }
                }
            }
        }
        const fieldToObj = (obj) => {
            for (let key in obj) {
                if (typeof (obj[key]) === 'string') {
                    obj[key] = {
                        description: obj[key]
                    }
                } else {
                    fieldToObj(obj[key])
                }
            }
        }
        const tableOperation = {
            addClick() {
                saveForm.title = "新增接口"
                saveForm.formClear()
                saveForm.visible = true
            }, editClick({id, pid, name, url, param, paramValid, json, response, open, authentication}) {
                saveForm.title = "编辑接口"
                saveForm.formClear()
                Object.assign(saveForm.formData, {id, pid, name, url, param, paramValid, json, response, open, authentication})
                saveForm.visible = true
            }, copyClick({pid, name, url, param, paramValid, json, response, open, authentication}) {
                saveForm.title = "新增接口"
                saveForm.formClear()
                Object.assign(saveForm.formData, {pid, name, url, param, paramValid, json, response, open, authentication})
                saveForm.visible = true
            }, copyDirClick({id, url, name}) {
                copyDirFormData.value = {id, url, name}
                copyDirVisible.value = true
            }, configClick({id}) {
                configFormData.value = {id, type: '0', info: ['0', '1', '2'], table: configFormData.value.table}
                configVisible.value = true
            }, testClick({id, url, token, param, paramValid}) {
                testForm.formClear()
                let paramType
                if (param) {
                    //低代码
                    paramType = paramValid
                    if (paramType) {
                        let a = JSON.parse(param)
                        let b = JSON.parse(paramType)
                        fieldToObj(a);
                        paramType = JSON.stringify(_.merge(a, b), null, 4)
                        param = '{}'
                    }
                } else {
                    //swagger
                    swaggerData = JSON.parse(JSON.stringify(swaggerDataSource))
                    paramType = swaggerData.paths['/' + url]?.post?.requestBody?.content['application/json']?.schema['$ref']
                    if (paramType) {
                        paramType = paramType.replace('#/components/schemas/', '')
                        let schema = paramType
                        let properties = swaggerData.components.schemas[paramType]?.properties || {}
                        let requireds = swaggerData.components.schemas[paramType]?.required || []
                        requireds.forEach(key => properties[key].required = true)
                        paramType = properties
                        param = {}
                        getSwaggerRef(paramType, param, schema)
                        param = JSON.stringify(param, null, 4)
                        paramType = JSON.stringify(paramType, null, 4)
                    }
                }
                Object.assign(testForm.formData, {id, url, token, param, paramType})
                testForm.visible = true
            }, paramClick({url, param}) {
                paramForm.formClear()
                swaggerData = JSON.parse(JSON.stringify(swaggerDataSource))
                let req = swaggerData.paths['/' + url]?.post?.requestBody?.content['application/json']?.schema['$ref']
                let res = swaggerData.paths['/' + url]?.post?.responses['200']?.content['*/*']?.schema['$ref']
                if (req) {
                    req = req.replace('#/components/schemas/', '')
                    let schema = req
                    let properties = swaggerData.components.schemas[req]?.properties || {}
                    let requireds = swaggerData.components.schemas[req]?.required || []
                    requireds.forEach(key => properties[key].required = true)
                    req = properties
                    getSwaggerRef(req, {}, schema)
                    req = JSON.stringify(req, null, 4)
                }
                if (res) {
                    res = res.replace('#/components/schemas/', '')
                    let schema = res
                    let properties = swaggerData.components.schemas[res]?.properties || {}
                    let requireds = swaggerData.components.schemas[res]?.required || []
                    requireds.forEach(key => properties[key].required = true)
                    res = properties
                    getSwaggerRef(res, {}, schema)
                    res = JSON.stringify(res, null, 4)
                }
                Object.assign(paramForm.formData, {url, req, res})
                paramForm.visible = true
            }, ruleClick({id, url, param, paramValid}) {
                ruleForm.formClear()
                let paramType
                if (param) {
                    //低代码
                    paramType = paramValid
                    if (paramType) {
                        let a = JSON.parse(param)
                        let b = JSON.parse(paramType)
                        fieldToObj(a);
                        paramType = JSON.stringify(_.merge(a, b), null, 4)
                        param = '{}'
                    }
                } else {
                    //swagger
                    swaggerData = JSON.parse(JSON.stringify(swaggerDataSource))
                    paramType = swaggerData.paths['/' + url]?.post?.requestBody?.content['application/json']?.schema['$ref']
                    if (paramType) {
                        paramType = paramType.replace('#/components/schemas/', '')
                        let schema = paramType
                        paramType = swaggerData.components.schemas[paramType]?.properties || {}
                        param = {}
                        getSwaggerRef(paramType, param, schema)
                        param = JSON.stringify(param, null, 4)
                        paramType = JSON.stringify(paramType, null, 4)
                    }
                }
                Object.assign(ruleForm.formData, {id, url, param, paramType})
                ruleForm.visible = true
            }, async save(data) {
                await api.save(data);
                saveForm.visible = false
                await loadData.loadTable()
            }, async saveRule(data) {
                await api.saveRule(data);
                ruleForm.visible = false
                await loadData.loadTable()
            }, async del({id}) {
                await api.del(id)
                await loadData.loadTable()
            }, async autoTest(data) {
                await api.setAutoTest({id: data.id, autoTest: data.autoTest})
            }, async copyDir() {
                (await getRef(copyDirFormRef)).validate(async (valid) => {
                    await api.copyDir(copyDirFormData.value)
                    copyDirVisible.value = false
                    await loadData.loadTable()
                })
            }, async open(data) {
                await api.setOpen({id: data.id, open: data.open})
            }, async authentication(data) {
                await api.setAuthentication({id: data.id, authentication: data.authentication})
            }, async config() {
                (await getRef(configFormRef)).validate(async (valid) => {
                    await api.config(configFormData.value)
                    configVisible.value = false
                    await loadData.loadTable()
                })
            }
        }
        const init = (async () => {
            [myTable, saveForm, testForm, ruleForm, paramForm] = await getRefs([myTableRef, saveFormRef, testFormRef, ruleFormRef, paramFormRef])
            Promise.all([loadData.loadTable(), loadData.loadSwagger(), loadData.loadTableList()])
        })()
        const filterNode = (tree, keyword) => {
            return tree.filter(node => {
                const match = node.name.toLowerCase().indexOf(keyword.toLowerCase()) !== -1;
                if (!match && node.children && node.children.length) {
                    node.children = filterNode(node.children, keyword);
                }
                return match || (node.children && node.children.length);
            });
        }
        Vue.watch(() => search.name, (val) => {
            if (val == '') myTable.tableData = tableDataSource.value
            else {
                myTable.tableData = filterNode(JSON.parse(JSON.stringify(tableDataSource.value)), val)
            }
        })
        return {
            search, myTableRef, saveFormRef, testFormRef, ruleFormRef, paramFormRef,
            loadData, tableDataSource, tableOperation, dateFormat, copyDirVisible,
            copyDirFormData, configVisible, tableList, configFormData,
            copyDirFormRef, configFormRef
        }
    }, components: {
        mySearch: (await import('/component/search/js/index.js')).default,
        myTable: (await import('/component/table/js/index.js')).default,
        confirmButton: (await import('/component/confirm_button/js/index.js')).default,
        saveForm: (await import('/page/interface_manager/js/save.js')).default,
        testForm: (await import('/page/interface_manager/js/test.js')).default,
        ruleForm: (await import('/page/interface_manager/js/rule.js')).default,
        paramForm: (await import('/page/interface_manager/js/param.js')).default,
    }
}